﻿///////////////////////////////////////////////////////////////////////////
// 文件名:     progressmanage.h
// 描述:
// 作者:      颜磊
// 创建时间:   2024-06-08 23:42
///////////////////////////////////////////////////////////////////////////
#ifndef PROGRESSMANAGE_H
#define PROGRESSMANAGE_H

#include "Userenv.h"
#include "string"
#include "windows.h"
#include <assert.h>
#include <chrono>
#include <list>
#include <map>
#include <psapi.h>
#include <tlhelp32.h> //进程快照函数头文件
#include <unordered_map>

#pragma comment(lib, "OleAut32.lib")
#pragma comment(lib, "comsuppw.lib")
#pragma comment(lib, "Userenv.lib")
#pragma comment(lib, "Advapi32.lib")

using namespace std;

struct LastTime
{
    int64_t last_time;
    int64_t last_system_time;
};

// 使用RAII管理进程句柄
class HandleGuard
{
public:
    explicit HandleGuard(HANDLE h)
        : handle(h)
    {
    }
    ~HandleGuard()
    {
        if (handle)
            CloseHandle(handle);
    }

    operator HANDLE() const { return handle; }

    HandleGuard(const HandleGuard &) = delete;
    HandleGuard &operator=(const HandleGuard &) = delete;

private:
    HANDLE handle;
};

class LPVOIDeGuard
{
public:
    explicit LPVOIDeGuard(LPVOID p)
        : pEnv(p)
    {
    }
    ~LPVOIDeGuard()
    {
        if (pEnv)
            DestroyEnvironmentBlock(pEnv);
        ;
    }

    LPVOIDeGuard(const LPVOIDeGuard &) = delete;
    LPVOIDeGuard &operator=(const LPVOIDeGuard &) = delete;

private:
    LPVOID pEnv;
};

struct ProcessTimeData
{
    int64_t last_system_time = 0;
    int64_t last_time = 0;
    std::chrono::steady_clock::time_point last_update;
};

class ProgressManage
{
public:
    // 获取进程的cpu使用率，返回-1失败
    bool get_cpu_usage(DWORD &processId, float &cpu_usage);
    // 获取进程的cpu平均使用率，返回-1失败
    bool get_cpu_usage_mean(DWORD &processId, float &cpu_usage);

public:
    ProgressManage();
    //检测进程是否存在（通过进程名）
    static bool checkProcessByName(string &strExe);
    //检测进程是否存在（通过进程Id）
    static bool checkProcessById(DWORD &processId);
    //根据进程名获取进程id
    static bool getProcessIdByName(string &strExe, DWORD &processId);
    // 获取进程全路径
    static bool GetProcessFullPath(DWORD dwPID, std::string &fullPath);
    //根据进程地址获取进程id
    static bool getProcessIdByPath(string &proPath, DWORD &processId);
    //获取winlogon进程id
    static bool getWinlogonProcessId(DWORD &processId);
    //提升当前进程权限
    static bool enableDebugPriv();
    //根据进程地址获取进程id集合
    static list<DWORD> getProcessIdsByPath(string &proPath);
    //根据进程id获取进程名
    static string getProcessNameById(DWORD &processId);
    //根据进程id获取运行时长(秒)
    static bool getProcessTimeById(DWORD &processId, uint64_t &time);
    //结束指定进程
    static void killProcessById(DWORD &processId);

    // 获取进程内存和虚拟内存使用量，返回-1失败，0成功
    static bool get_memory_usage(DWORD &processId, uint64_t &mem, uint64_t &vmem);

    // 获取进程总共读和写的IO字节数，返回-1失败，0成功
    static bool get_io_bytes(DWORD &processId, uint64_t &read_bytes, uint64_t &write_bytes);

    //根据进程路径启动进程(服务)
    static bool startProcessByPath_S(string &path);
    //根据进程路径启动进程(程序)
    static bool startProcessByPath_A(string &path);
    static bool stopProcessByPath(string &path);
    //获取进程token
    static bool getProcessToken(HANDLE *hToken);

private:
    //服务程序启动外部程序
    static bool ServerRunWndProcess(LPWSTR lpExePath);
    //服务程序启动外部程序 - 管理员身份
    static bool serverCreateProcessAsAdmin(string &path);
    static bool serverCreateProcessAsAdmin2(string &path);
    //桌面程序启动外部程序 - 管理员身份
    static bool appCreateProcessAsAdmin(string &path);

private:
    //      map<unsigned long,LastTime> lastTimeMap;
    std::unordered_map<DWORD, ProcessTimeData> processTimeMap;
};

#endif // PROGRESSMANAGE_H
